package org.mte.sakn.file;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;

public class FileSystemImpl implements FileSystem {

	/**
	 * root.
	 */
	protected File root = null;

	/**
     * filter
	 */
    protected FilenameFilter filter = null;

    /**
     * separator
     */
	protected String separator = System.getProperty("file.separator");

	/**
	 * dirs
	 */
	protected ArrayList<FileSystem> dirs = null;

	/**
	 * files
	 */
	protected ArrayList<FileObject> files = null;
	
	/**
	 * FileSystemImpl
	 */
	public FileSystemImpl() {
	}
	
	/**
	 * FileSystemImpl
	 * @param root
	 */
	public FileSystemImpl(File root) {
		this.root = root;
        try {
        	build();
        } catch (Exception e) {
        	e.printStackTrace();
        }
	}

	/**
	 * FileSystemImpl
	 * @param path
	 */
	public FileSystemImpl(String path) {
		root = new File(path);
        try {
        	build();
        } catch (Exception e) {
        	e.printStackTrace();
        }
	}

    /**
     * FileSystemImpl
     * @param path
     * @param filter
     */
    public FileSystemImpl(String path, FilenameFilter filter) {
        root = new File(path);
        this.filter = filter;
        try {
        	build();
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }

    /**
     * FileSystemImpl
     * @param root
     * @param filter
     */
    public FileSystemImpl(File root, FilenameFilter filter) {
        this.root = root;
        this.filter = filter;
        try {
        	build();
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }
    
	/**
	 * getRoot
	 * @return root
	 */
	public File getRoot() {
		return root;
	}
    
    /**
     * Costruisce l'albero del file system creando
     * gli oggetti directory e file
     */
    protected void build() throws Exception {
        if (root.isDirectory()) {
            File[] resources = root.listFiles();
            if (resources != null) {
            	int length = resources.length;
                for (int i = 0; i < length; i++) {
                    if (resources[i] != null) {
                    	boolean isAccepted = false;
                    	if (filter != null && filter.accept(resources[i], resources[i].getName())) {
                    		isAccepted = true;
                    	} else if (filter == null) {
                    		isAccepted = true;
                    	}
                    	if (isAccepted) {
	                        if (resources[i].isDirectory()) {
	                            buildDir(resources[i]);
	                        } else {
	                        	buildFile(resources[i]);
	                        }
                    	}
                    }
                }
            }
            //sort();
        } else {
        	System.out.println(root.getPath() + " is not a directory or it is abstract!");
        }
    }
    
/*    private void sort() {
    	
    }*/
    
    /**
     * buildDir
     *
     * @param fDir
     */
    private void buildDir(File fDir) {
        if (dirs == null) {
        	dirs = new ArrayList<FileSystem>();
        }
        dirs.add(new FileSystemImpl(fDir, filter));
    }

    /**
     * buildFile
     *
     * @param file
     */
    private void buildFile(File file) throws Exception {
        if (files == null) {
        	files = new ArrayList<FileObject>();
        }
        files.add(new FileObjectImpl(file));
    }
    
    /**
     * Crea tutto il percorso di un oggetto FileSystemManager
     * astratto
     *
     * @return true se le directory sono create
     * @throws Exception
     */
    public boolean makeFileSytemPath() throws Exception {
    	return root.mkdirs();
    }
    
	/**
	 * getDirs
	 * @return dirs
	 */
	public ArrayList<FileSystem> getDirs() {
		return dirs;
	}
	
	/**
	 * getFiles
	 * @return fsFiles
	 */
	public ArrayList<FileObject> getFiles() {
		return files;
	}
	
	/**
	 * getDir
	 * @param index
	 * @return fsDir
	 */
	public FileSystem getDir(int index) {
		FileSystem fsDir = null;
		if (dirs != null) {
			fsDir = dirs.get(index);
		}
		return fsDir;
	}

	/**
	 * getFsFile
	 * @param index
	 * @return fsFile
	 */
	public FileObject getFile(int index) {
		FileObject fsFile = null;
		if (files != null) {
			fsFile = files.get(index);
		}
		return fsFile;
	}

	public FileObject createFileObject(String path) {
		return new FileObjectImpl(path);
	}
	
	public void printToOut() {
		printToOut(true);
	}
	
	public void printToOut(boolean isRoot) {
		if (isRoot) {
			System.out.println("---------------------------------");
			System.out.println("root: " + root.getName());
			System.out.println("---------------------------------");
		}
		if (dirs != null) {
			for (FileSystem dir : dirs) {
				System.out.println("---------------------------------");
				System.out.println("dir: " + dir.getRoot().getName());
				System.out.println("---------------------------------");
				if (dir.getFiles() != null) {
					for (FileObject fo : dir.getFiles()) {
						System.out.println("file: " + fo.getName());
					}
					
				}
				System.out.println("---------------------------------");
				dir.printToOut(false);
			}
		}
		if (files != null && isRoot) {
			System.out.println("---------------------------------");
			for (FileObject fo : files) {
				System.out.println("file: " + fo.getName());
			}
		}
	}
}
